﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Xml.Linq;
using System.Windows;

namespace OpticalPowerMeter
{

    /// <summary>
    /// 关于机型的设置，用于添加、删除、配置机型的相关信息
    /// </summary>
    public class ProductManagement
    {
        private static ProductManagement pwm = null;

        /// <summary>
        /// 产品清单发生变化时，产生事件。由注册界面调用，例如主界面的产品型号选择清单
        /// </summary>
        public event EventHandler<ProductListChangedArgs> ProductNameListChanged;

        //配置文件保存的完整名称
        private string FileName = System.Environment.CurrentDirectory + "\\Config\\" + "Product.xml";


        //单例模式，将构造器设为私有
        private ProductManagement() { }


        /// <summary>
        /// 获取对象的方式，本类为单例模式，外部无法通过构造函数创建对象
        /// </summary>
        /// <returns>ProductManagement对象</returns>
        public static ProductManagement GetInstance()
        {
            if (pwm == null){
                pwm = new ProductManagement();
            }
            return pwm;
        }

        
        //添加波长
        private void AddWavelength(string productName,string wavelength)
        {
            if (!File.Exists(FileName))
            {
                return;
            }
            XElement root = XElement.Load(FileName);
            #region 查找对应机型的节点
            var result = (from elem in root.Elements("Product")
                          where elem.Attribute("ProductName") != null
                          && elem.Attribute("ProductName").Value.Equals(productName)
                          select elem
                          );
            if (result.Count() == 0) { return; }
            #endregion
            XElement productElement = result.SingleOrDefault();
            XElement wavelengthElement = new XElement("Wavelength",new XAttribute("Wavelength",wavelength));
            var wavelengthResult = (from elem in productElement.Elements("Wavelength")
                                    where elem.Attribute("Wavelength") != null
                                    select elem);
            #region 如果不存在任何波长，则直接写入一个波长
            if (wavelengthResult.Count() == 0) {
                productElement.Add(wavelengthElement);
                root.Save(FileName);
                return;
            }
            #endregion
            #region 如果波长列表非空，则在比当前波长值大的波长前面插入当前波长
            foreach (XElement element in wavelengthResult)
            {
                int currentWavelength = Convert.ToInt16(element.Attribute("Wavelength").Value);
                int paramWavelength = Convert.ToInt16(wavelength);
                if(currentWavelength > paramWavelength)
                {
                    XElement xElement = element;
                    xElement.AddBeforeSelf(new XElement("Wavelength",new XAttribute("Wavelength",wavelength)));
                    root.Save(FileName);
                    return;
                }
            }
            #region 如果没有比当前波长大的波长，则将当前波长写在最后一个波长后面
            XElement lastElement = wavelengthResult.Last();
            lastElement.AddAfterSelf(new XElement("Wavelength", new XAttribute("Wavelength", wavelength)));
            root.Save(FileName);
            #endregion
            #endregion
        }


        //删除波长
        private void DeleteWavelength(string productName, string wavelength)
        {
            if (!File.Exists(FileName))
            {
                return;
            }
            XElement root = XElement.Load(FileName);
            var result = (from elem in root.Elements("Product")
                          where elem.Attribute("ProductName") != null
                          && elem.Attribute("ProductName").Value.Equals(productName)
                          select elem
                          );
            if (result.Count() == 0) { return; }
            XElement productElement = result.SingleOrDefault();
            var waveResult = (from elem in productElement.Elements("Wavelength")
                              where elem.Attribute("Wavelength") != null
                              && elem.Attribute("Wavelength").Value.Equals(wavelength)
                              select elem
                              );
            if (waveResult.Count() == 0) { return; }
            XElement waveElement = waveResult.SingleOrDefault();
            waveElement.Remove();
            root.Save(FileName);
        }


        ////添加线性点
        //private void AddLinear(string productName,Linear linear) {
        //    if (!File.Exists(FileName))
        //    {
        //        return;
        //    }
        //    XElement root = XElement.Load(FileName);
        //    #region 查找对应机型的节点
        //    var result = (from elem in root.Elements("Product")
        //                  where elem.Attribute("ProductName") != null
        //                  && elem.Attribute("ProductName").Value.Equals(productName)
        //                  select elem
        //                  );
        //    if (result.Count() == 0) { return; }
        //    int index = linear.Index;
        //    XElement linearElement = new XElement("Linear", new XAttribute("Index", index),
        //        new XElement("P1", linear.P1), new XElement("P2", linear.P2));  //线性点
        //    XElement productElement = result.SingleOrDefault();
        //    #endregion
        //    var linearResult = (from elem in productElement.Elements("Linear")
        //                        where elem.Attribute("Index") != null
        //                        select elem);
        //    #region 如果不存在任何Linear节点，则直接写入节点
        //    if (linearResult.Count() == 0) {
        //        productElement.Add(linearElement);
        //        root.Save(FileName);
        //        return;
        //    }
        //    #endregion

        //    #region 对比当前值的Index与传入的Index的大小，如果匹配，则修改该节点。如果当前的值大于传入值，则在当前位置前面插入节点
        //    List<XElement> linearList = linearResult.ToList();
        //    for (int i = 0; i < linearList.Count(); i++)
        //    {
        //        int currentIndex = Convert.ToInt16(linearList[i].Attribute("Index").Value.ToString());
        //        #region 如果有对应的线性点，则刷新线性点的值
        //        if (currentIndex == index)
        //        {
        //            XElement xElement = linearList[i];
        //            var p1Result = (from elem in xElement.Elements("P1")
        //                            select elem
        //                            ).SingleOrDefault();
        //            p1Result.Value = linear.P1.ToString();

        //            var p2Result = (from elem in xElement.Elements("P2")
        //                            select elem
        //                ).SingleOrDefault();
        //            p2Result.Value = linear.P2.ToString();
        //            root.Save(FileName);
        //            return;
        //        }
        //        #endregion

        //        #region 如果索引号大于传入值，则在当前位置前插入一个节点信息
        //        if (currentIndex > index)
        //        {
        //            XElement xElement = linearList[i];
        //            xElement.AddBeforeSelf(linearElement);
        //            root.Save(FileName);
        //            return;
        //        }
        //        #endregion
        //    }
        //    XElement endElement = linearList[linearList.Count - 1];
        //    endElement.AddAfterSelf(linearElement);
        //    root.Save(FileName);
        //    #endregion
        //}


        //删除线性点
        //private void DeleteLinear(string productName,List<Linear> linears) {
        //    if (!File.Exists(FileName))
        //    {
        //        return;
        //    }
        //    XElement root = XElement.Load(FileName);
        //    var result = (from element in root.Elements("Product")
        //                  where element.Attribute("ProductName") != null
        //                  && element.Attribute("ProductName").Value.Equals(productName)
        //                  select element
        //                  );
        //    if (result.Count() == 0)
        //    {
        //        return;
        //    }
        //    XElement productElement = result.SingleOrDefault();
        //    List<Linear> localLinears = GetLinearList(productName); //本地线性点
        //    Dictionary<int, Linear> linearDic = new Dictionary<int, Linear>();
        //    foreach(Linear linear in linears)
        //    {
        //        int index = linear.Index;
        //        linearDic.Add(index, linear);
        //    }
        //    foreach(Linear localLinear in localLinears)
        //    {
        //        int localIndex = localLinear.Index;
        //        if (!linearDic.Keys.Contains(localIndex))
        //        {
        //            XElement linearXElement = (from elem in productElement.Elements("Linear")
        //                                where elem.Attribute("Index") != null
        //                                && elem.Attribute("Index").Value.Equals(localIndex.ToString())
        //                                select elem
        //                              ).SingleOrDefault();
        //            linearXElement.Remove();
        //        }
        //    }
        //    root.Save(FileName);
        //}


        //保存复测点
        //public void SaveCheckPoint(string productName,Dictionary<string,List<CheckPoint>> checkPointDic) {
        //    if (!File.Exists(FileName))
        //    {
        //        return;
        //    }
        //    XElement root = XElement.Load(FileName);
        //    var result = (from element in root.Elements("Product")
        //                  where element.Attribute("ProductName") != null
        //                  && element.Attribute("ProductName").Value.Equals(productName)
        //                  select element
        //      );
        //    //配置文件中，应有且只有一个该机型的配置清单
        //    if (result.Count() != 1)
        //    {
        //        return;
        //    }
        //    XElement productElement = result.SingleOrDefault();
        //    string[] wavlengthArr = checkPointDic.Keys.ToArray();
        //    #region 遍历每一个波长，将复查点写入配置文件
        //    foreach (string wavlength in wavlengthArr)
        //    {
        //         var wavelengthResult = (from element in productElement.Elements("Wavelength")
        //                                      where element.Attribute("Wavelength") != null
        //                                      && element.Attribute("Wavelength").Value.Equals(wavlength)
        //                                      select element
        //                                      );
        //        if(wavelengthResult.Count() != 1)
        //        {
        //            continue;
        //        }
        //        XElement wavelengthElement = wavelengthResult.SingleOrDefault();
        //        wavelengthElement.RemoveNodes(); //清除原节点数据
        //        #region 将传入的复查点写入波长对应的节点
        //        List<CheckPoint> checkPointList = checkPointDic[wavlength];
        //        foreach(CheckPoint check in checkPointList)
        //        {
        //            XElement checkElement = new XElement("Check",new XAttribute("Power",check.CheckPower),new XElement("Limit",check.Limit));
        //            wavelengthElement.Add(checkElement);
        //        }
        //        #endregion
        //    }
        //    root.Save(FileName);
        //    #endregion
        //}


        /// <summary>
        /// 把机型的相关参数保存在本地
        /// </summary>
        /// <param name="product">产品对象</param>
        public void SaveData(Product product)
        {
            string path = System.Environment.CurrentDirectory + "\\Config";
            if (!Directory.Exists(path))
            {
                Directory.CreateDirectory(path);
            }
            #region 如果文件不存在，添加文件
            if (!File.Exists(FileName))
            {
                XDocument xDoc = new XDocument(
                    new XDeclaration("1.0", "utf-8", "yes"),
                    new XElement("Config"));
                xDoc.Save(FileName);
            }
            #endregion

            XElement root = XElement.Load(FileName);
            var result = (from element in root.Elements("Product")
                          where element.Attribute("ProductName") != null
                          && element.Attribute("ProductName").Value.Equals(product.ProductName)
                          select element
                          );

            #region 如果配置文件中不存在该机型名称，则直接将该机型名称、波长列表、线性点添加到配置文件
            if (result.Count() == 0)
            {
                XElement productElement = new XElement("Product",
                    new XAttribute("ProductName", product.ProductName));
                //遍历波长列表，添加到配置文件
                foreach (string wavelength in product.Wavelengthes)
                {
                    XElement wavelengthElement = new XElement("Wavelength",
                        new XAttribute("Wavelength", wavelength));
                    productElement.Add(wavelengthElement);
                }
                ////遍历线性点列表，添加到配置文件
                //foreach (Linear linear in product.Linears)
                //{
                //    string index = linear.Index.ToString();
                //    string p1 = linear.P1.ToString();
                //    string p2 = linear.P2.ToString();
                //    XElement linearElement = new XElement("Linear",
                //        new XAttribute("Index", index), new XElement("P1", p1), new XElement("P2", p2));
                //    productElement.Add(linearElement);
                //}
                root.Add(productElement);
                ProductListChanged(product.ProductName, "Add");
                root.Save(FileName);
                return;
            }
            #endregion

            #region 如果配置文件中存在该机型名称，则对比配置文件中的波长列表与传入的波长列表、线性点差异部分修改
            bool isChanged = false;
            try
            {
                XElement productElement = result.Single();
                #region 遍历传入的波长列表，如果配置文件中不存在，则添加该波长
                foreach (string wavelength in product.Wavelengthes)
                {
                    var wavelengthResult = (from waveElement in productElement.Elements("Wavelength")
                                            where waveElement.Attribute("Wavelength") != null
                                            && waveElement.Attribute("Wavelength").Value.Equals(wavelength)
                                            select waveElement
                                            );
                    if (wavelengthResult.Count() == 0)
                    {
                        AddWavelength(product.ProductName,wavelength);
                    }
                }
                #endregion

                #region 如果配置文件中存在该波长，但该波长未选中，则将配置文件中的波长去除
                List<string> wavelengthList = GetWaveList(product.ProductName);
                foreach (string wavlength in wavelengthList)
                {
                    if (!product.Wavelengthes.Contains(wavlength))
                    {
                        DeleteWavelength(product.ProductName, wavlength);
                    }
                }
                #endregion

                //#region 添加线性点
                //List<Linear> linearList = product.Linears;
                //foreach(Linear linear in linearList)
                //{
                //    AddLinear(product.ProductName, linear);
                //}
                //#endregion

                //#region 将配置文件中存在，本次传入中不存在的线性点删除
                //if (linearList.Count < GetLinearList(product.ProductName).Count)
                //{
                //    DeleteLinear(product.ProductName, product.Linears);
                //}
                //#endregion

                if (isChanged)
                {
                    root.Save(FileName);
                }
            }catch(Exception e) { throw e; }
            #endregion
        }


        /// <summary>
        /// 删除本地配置文件中的相应机型及其配置
        /// </summary>
        /// <param name="productName">机型名称</param>
        public void DeleteProduct(string productName)
        {
            if (!File.Exists(FileName))
            {
                return;
            }
            XElement root = XElement.Load(FileName);
            var result = (from elem in root.Elements("Product")
                          where elem.Attribute("ProductName") != null
                          && elem.Attribute("ProductName").Value.Equals(productName)
                          select elem
                          );
            if (result.Count() == 0)
            {
                return;
            }
            IEnumerator<XElement> enumerator = result.GetEnumerator();
            while (enumerator.MoveNext())
            {
                enumerator.Current.Remove();
            }
            ProductListChanged(productName,"Remove");
            root.Save(FileName);
        }


        ////获取机型的复查点
        //public Dictionary<string,List<CheckPoint>> GetCheckPointDic(string productname) {
        //    if (!File.Exists(FileName))
        //    {
        //        return null;
        //    }
        //    XElement root = XElement.Load(FileName);
        //    var productResult = (from element in root.Elements("Product")
        //                         where element.Attribute("ProductName") != null
        //                         && element.Attribute("ProductName").Value.Equals(productname)
        //                         select element
        //                         );
        //    if (productResult.Count() == 0)
        //    {
        //        return null;
        //    }
        //    XElement productElement = productResult.SingleOrDefault();
        //    var waveResult = (from elem in productElement.Elements("Wavelength")
        //                      select elem);
        //    if (waveResult.Count() == 0)
        //    {
        //        return null;
        //    }
        //    //遍历每个波长，读取对应的复测点
        //    Dictionary<string, List<CheckPoint>> checkPointDic = new Dictionary<string, List<CheckPoint>>();
        //    foreach (object waveObj in waveResult) {
        //        XElement waveElement = (XElement)waveObj;
        //        string wavelength = waveElement.Attribute("Wavelength").Value.Trim(); //波长
        //        var checkPointsResult = (from elem in waveElement.Elements("Check")
        //                                 select elem
        //                                 );
        //        if (checkPointsResult.Count() == 0)
        //        {
        //            continue;
        //        }
        //        List<CheckPoint> checkPointList = new List<CheckPoint>();
        //        foreach(object checkObj in checkPointsResult) //遍历复查点，添加到清单
        //        {
        //            XElement checkElement = (XElement)checkObj;
        //            string power = checkElement.Attribute("Power").Value.Trim();
        //            XElement limitElement = (from ele in checkElement.Elements("Limit")
        //                               select ele).SingleOrDefault();
        //            string limit = limitElement.Value.Trim();
        //            CheckPoint check = new CheckPoint();
        //            check.CheckPower = Convert.ToDouble(power);
        //            check.Limit = Convert.ToDouble(limit);
        //            checkPointList.Add(check);
        //        }
        //        checkPointDic.Add(wavelength,checkPointList);
        //    }
        //    return checkPointDic;
        //}


        ////获取机型的线性清单
        //public List<Linear> GetLinearList(string productName) {
        //    if (!File.Exists(FileName))
        //    {
        //        return null;
        //    }
        //    XElement root = XElement.Load(FileName);
        //    var result = (from element in root.Elements("Product")
        //                  where element.Attribute("ProductName") != null
        //                  && element.Attribute("ProductName").Value.Equals(productName)
        //                  select element
        //                  );
        //    if (result.Count() == 0)
        //    {
        //        return null;
        //    }
        //    try {
        //        List<Linear> linearList = new List<Linear>();
        //        XElement productElement = result.SingleOrDefault();
        //        var linearResult = (from element in productElement.Elements("Linear")
        //                            select element);
        //        if (linearResult.Count() == 0)
        //        {
        //            return null;
        //        }
        //        #region 遍历线性点，将内容添加到配置文件
        //        foreach(XElement elem in linearResult)
        //        {
        //            int index = Convert.ToInt16(elem.Attribute("Index").Value.ToString());
        //            double p1 = Convert.ToDouble(elem.Element("P1").Value.ToString());
        //            double p2 = Convert.ToDouble(elem.Element("P2").Value.ToString());
        //            Linear linear = new Linear();
        //            linear.Index = index;
        //            linear.P1 = p1;
        //            linear.P2 = p2;
        //            linearList.Add(linear);
        //        }
        //        #endregion
        //        return linearList;
        //    } catch(Exception e) { throw e; }
        //}


        /// <summary>
        /// 获取指定机型的波长列表
        /// </summary>
        /// <param name="productName"></param>
        /// <returns></returns>
        public List<string> GetWaveList(string productName)
        {
            //文件不存在，直接返回null
            if (!File.Exists(FileName))
            {
                return null;
            }
            XElement root = XElement.Load(FileName);
            var result = (from element in root.Elements("Product")
                          where element.Attribute("ProductName") != null
                          && element.Attribute("ProductName").Value.Equals(productName)
                          select element
                          );
            if (result.Count() == 0)
            {
                return null;
            }
            try
            {
                List<string> wavelengthList = new List<string>();
                var wavelengthes = (from element in result.Single().Descendants("Wavelength")
                                    where element.Attribute("Wavelength") != null
                                    select element.Attribute("Wavelength"));
                int count = wavelengthes.Count();
                IEnumerator<XAttribute> enumerator = wavelengthes.GetEnumerator();
                while (enumerator.MoveNext())
                {
                    wavelengthList.Add(enumerator.Current?.Value);
                }
                return wavelengthList;
            }
            catch (Exception e) { throw e; }
        }


        //获取机型清单
        public List<string> GetProductList()
        {
            if (!File.Exists(FileName))
            {
                return null;
            }
            XElement root = XElement.Load(FileName);
            var result = (from elem in root.Elements("Product")
                          where elem.Attribute("ProductName") != null
                          select elem.Attribute("ProductName"));
            if (result.Count() == 0)
            {
                return null;
            }
            List<string> productNameList = new List<string>();
            IEnumerator<XAttribute> enumerator = result.GetEnumerator();
            while (enumerator.MoveNext())
            {
                productNameList.Add(enumerator.Current?.Value);
            }
            return productNameList;
        }


        ////机型名称节点发生变化时，产生一个事件，由订阅者使用
        private void ProductListChanged(string productname,string changeType)
        {
            ProductListChangedArgs changedArgs = new ProductListChangedArgs();
            changedArgs.Productname = productname;
            changedArgs.ChangeType = changeType;
            ProductNameListChanged?.Invoke(this, changedArgs);
        }

    }
}
